/*
 * Copyright 2011-2012 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sabayframework.channel;


/**
 * Interface of a data channel is an abstraction for asynchronous communications between activities or for IO-bound load.
 * The interface is similar to the Queue interface. Additionally, it supports batch 
 * read/write operations and has a life-cycle state(open, closed, failed ).
 *  
 *  @author Alex Antonau
 * */
public interface Channel<T> {

	/**
	 * Returns a read lock for given number of available elements.
	 * This method does not wait for a lock it returns immediately with a 
	 * lock or null if lock is not currently available.
	 * @param size number of elements to lock  
	 * @return read Lock for the channel or null if a lock cannot be acquired at the moment.
	 * */
	Lock<T> getReadLock(int size);
	
	/**
	 * Immediately retrieves and removes first available element in this channel.
	 * @return first available element
	 * @throws IllegalStateException if channel is empty or blocked by another thread.
	 * */
	T remove() throws IllegalStateException;
	
	/**
	 * Returns a write lock for given number of available elements.
	 * This method does not wait for lock it returns immediately with a lock or null if lock
	 * is not currently available.  
	 * @param size number of elements to lock  
	 * @return read Lock for the channel or null if a lock cannot be acquired at the moment.
	 * */
	Lock<T> getWriteLock(int size);
	/**
	 * Immediately adds an element to this channel.
	 * @throws IllegalStateException if channel is full or blocked by another thread.
	 * */
	void add(T elem) throws IllegalStateException;
	
	/**
	 * Returns true if channel size is 0 or false otherwise.
	 * */
	boolean isEmpty();
	
	/**
	 * Returns true if channel has no space to insert an element or false otherwise.
	 * */
	boolean isFull();
	
	/**
	 * Returns number of elements in the channel
	 * @return
	 */
	int size();
	
	/**
	 * Returns maximum number of elements that the channel can hold.
	 * */
	int capacity();

	/**
	 * Returns number of elements that currently can be locked for write 
	 * */
	int freeSize();
	
	/**
	 * Closes input for this channel for write. Remaining elements still can be read.
	 */
	void close();
	/**
	 * Returns true if this channel is closed.
	 * @return true if this channel is closed, false-otherwise
	 */
	boolean isClosed();

	/**
	 * Signals an error in processing of data from this channel.
	 * Channel will be closed and cleared of existing elements.
	 * Failure of the channel can be checked by calling isFailed method. 
	 * */
	void fail(Throwable cause);

	/**
	 * Returns true if fail was called on this channel.
	 * */
	boolean hasFailed();

	/**
	 * Returns a Throwable that caused failure of channel processing.
	 * */
	Throwable getFailureCause();
		
	/**
	 * Waits if necessary for one of these conditions: count or more elements become 
	 * available for read or channel is closed or waiting time exceeds number of milliseconds 
	 * specified in timeout parameter.
	 * @param count number of elements to lock.
	 * @param timeout maximum waiting time in milliseconds.
	 * @return Lock object or null if lock was not acquired.   
	 * @throws InterruptedException if other thread has interrupted waiting.
	 * */
	Lock<T> waitForReadLock(int count, long timeout)throws InterruptedException;
	
	int hashCode();
	boolean equals(Object object);
}
